package com.ruoyi.jiaopei.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.jiaopei.domain.TbKj;
import com.ruoyi.jiaopei.domain.bo.TbKjBo;
import com.ruoyi.jiaopei.domain.vo.TbClassVo;
import com.ruoyi.jiaopei.domain.vo.TbCurriculumVo;
import com.ruoyi.jiaopei.service.ITbClassService;
import com.ruoyi.jiaopei.service.ITbCurriculumService;
import com.ruoyi.jiaopei.service.ITbKjService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.jiaopei.domain.bo.TbSortCurriculumBo;
import com.ruoyi.jiaopei.domain.vo.TbSortCurriculumVo;
import com.ruoyi.jiaopei.domain.TbSortCurriculum;
import com.ruoyi.jiaopei.mapper.TbSortCurriculumMapper;
import com.ruoyi.jiaopei.service.ITbSortCurriculumService;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 排课Service业务层处理
 *
 * @author macy
 * @date 2024-04-03
 */
@RequiredArgsConstructor
@Service
public class TbSortCurriculumServiceImpl implements ITbSortCurriculumService {

    private final TbSortCurriculumMapper baseMapper;
    private final ITbKjService kjService;
    private final ITbClassService classService;
    private final ITbCurriculumService curriculumService;

    /**
     * 查询排课
     */
    @Override
    public TbSortCurriculumVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }


    @Override
    public Long selectCount(Wrapper<TbSortCurriculum> queryWrapper) {
        return baseMapper.selectCount(queryWrapper);
    }

    /**
     * 查询排课列表
     */
    @Override
    public TableDataInfo<TbSortCurriculumVo> queryPageList(TbSortCurriculumBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<TbSortCurriculum> lqw = buildQueryWrapper2(bo);
        Page<TbSortCurriculumVo> result = baseMapper.selectPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询排课列表
     */
    @Override
    public List<TbSortCurriculumVo> queryList(TbSortCurriculumBo bo) {
        LambdaQueryWrapper<TbSortCurriculum> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<TbSortCurriculum> buildQueryWrapper2(TbSortCurriculumBo bo) {

        QueryWrapper<TbSortCurriculum> lqw1 = Wrappers.query();
        lqw1.like(StringUtils.isNotBlank(bo.getClassName()),"c.name", bo.getClassName());
        lqw1.like(StringUtils.isNotBlank(bo.getTeacherName()),"u.nick_name", bo.getTeacherName());


        LambdaQueryWrapper<TbSortCurriculum> lqw =lqw1.lambda();

        lqw.eq(bo.getClassId() != null, TbSortCurriculum::getClassId, bo.getClassId());
        lqw.eq(StringUtils.isNotBlank(bo.getStartDate()), TbSortCurriculum::getStartDate, bo.getStartDate());
        lqw.eq(StringUtils.isNotBlank(bo.getEndDate()), TbSortCurriculum::getEndDate, bo.getEndDate());
        lqw.eq(StringUtils.isNotBlank(bo.getStartHour()), TbSortCurriculum::getStartHour, bo.getStartHour());
        lqw.eq(StringUtils.isNotBlank(bo.getEndHour()), TbSortCurriculum::getEndHour, bo.getEndHour());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), TbSortCurriculum::getType, bo.getType());
        lqw.eq(bo.getFrequency() != null, TbSortCurriculum::getFrequency, bo.getFrequency());
        lqw.eq(StringUtils.isNotBlank(bo.getWeekly()), TbSortCurriculum::getWeekly, bo.getWeekly());
        lqw.eq(bo.getTeacherId() != null, TbSortCurriculum::getTeacherId, bo.getTeacherId());
        lqw.eq(bo.getLessonHours() != null, TbSortCurriculum::getLessonHours, bo.getLessonHours());
        lqw.eq(bo.getCreatedDate() != null, TbSortCurriculum::getCreatedDate, bo.getCreatedDate());
        return lqw;
    }

    private LambdaQueryWrapper<TbSortCurriculum> buildQueryWrapper(TbSortCurriculumBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TbSortCurriculum> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getClassId() != null, TbSortCurriculum::getClassId, bo.getClassId());
        lqw.eq(StringUtils.isNotBlank(bo.getStartDate()), TbSortCurriculum::getStartDate, bo.getStartDate());
        lqw.eq(StringUtils.isNotBlank(bo.getEndDate()), TbSortCurriculum::getEndDate, bo.getEndDate());
        lqw.eq(StringUtils.isNotBlank(bo.getStartHour()), TbSortCurriculum::getStartHour, bo.getStartHour());
        lqw.eq(StringUtils.isNotBlank(bo.getEndHour()), TbSortCurriculum::getEndHour, bo.getEndHour());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), TbSortCurriculum::getType, bo.getType());
        lqw.eq(bo.getFrequency() != null, TbSortCurriculum::getFrequency, bo.getFrequency());
        lqw.eq(StringUtils.isNotBlank(bo.getWeekly()), TbSortCurriculum::getWeekly, bo.getWeekly());
        lqw.eq(bo.getTeacherId() != null, TbSortCurriculum::getTeacherId, bo.getTeacherId());
        lqw.eq(bo.getLessonHours() != null, TbSortCurriculum::getLessonHours, bo.getLessonHours());
        lqw.eq(bo.getCreatedDate() != null, TbSortCurriculum::getCreatedDate, bo.getCreatedDate());
        return lqw;
    }



    /**
     * 新增排课
     */
    @Override
    @Transactional
    public Boolean insertByBo(TbSortCurriculumBo bo) {
        TbSortCurriculum add = BeanUtil.toBean(bo, TbSortCurriculum.class);
        validEntityBeforeSave(add,bo);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }

        validEntityAfterSave(add,bo);
        return flag;
    }

    /**
     * 修改排课
     */
    @Override
    public Boolean updateByBo(TbSortCurriculumBo bo) {
        TbSortCurriculum update = BeanUtil.toBean(bo, TbSortCurriculum.class);
        validEntityBeforeSave(update,bo);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TbSortCurriculum entity,TbSortCurriculumBo bo){
        if(null==entity.getId()){

            if(DateUtils.parseDate(entity.getStartDate()).before(DateUtils.addDays(new Date(),-1))){
                throw new ServiceException("上课日期不能选择过去的日期");
            }

            if(null==entity.getCreatedDate()){
                entity.setCreatedDate(new Date());
            }

            if(entity.getType().equals("1")){
                entity.setFrequency(Long.valueOf(1));
                entity.setEndDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,DateUtils.addDays(DateUtils.parseDate(entity.getStartDate()),entity.getFrequency().intValue())));

            }else if(entity.getType().equals("2")){
                if(StrUtil.isBlank(bo.getJsfs())){
                    throw new ServiceException("结束方式不能为空");
                }
                if(bo.getJsfs().equals("1")){
                    if(null==entity.getFrequency()){
                        throw new ServiceException("重复次数不能为空");
                    }
                    entity.setEndDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,DateUtils.addDays(DateUtils.parseDate(entity.getStartDate()),entity.getFrequency().intValue())));
                }else if(bo.getJsfs().equals("2")){
                    if(StrUtil.isBlank(entity.getEndDate())){
                        throw new ServiceException("到期结束 不能为空");
                    }

                    if(DateUtils.parseDate(entity.getEndDate()).before(DateUtils.parseDate(entity.getStartDate()))){
                        throw new ServiceException("到期结束日期不能小于开始日期");
                    }
                }
            }else if(entity.getType().equals("3")){
                if(StrUtil.isBlank(bo.getJsfs())){
                    throw new ServiceException("结束方式不能为空");
                }
                if(StrUtil.isBlank(bo.getWeekly())){
                    throw new ServiceException("结束方式不能为空");
                }
                if(bo.getJsfs().equals("1")){
                    if(null==entity.getFrequency()){
                        throw new ServiceException("重复次数不能为空");
                    }
                    entity.setEndDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,DateUtils.addDays(DateUtils.parseDate(entity.getStartDate()),entity.getFrequency().intValue())));
                }else if(bo.getJsfs().equals("2")){
                    if(StrUtil.isBlank(entity.getEndDate())){
                        throw new ServiceException("到期结束 不能为空");
                    }
                    if(DateUtils.parseDate(entity.getEndDate()).before(DateUtils.parseDate(entity.getStartDate()))){
                        throw new ServiceException("到期结束日期不能小于开始日期");
                    }
                }
            }else{
                throw new ServiceException("不支持的类型");
            }

        }
    }

    private void validEntityAfterSave(TbSortCurriculum entity,TbSortCurriculumBo bo){
        if(null!=entity.getId()){

            TbKjBo kjBo=null;
            TbClassVo classVo=classService.queryById(entity.getClassId());
            if(null==classVo){
                throw new ServiceException("班级不存在");
            }

            TbCurriculumVo curriculumVo=curriculumService.queryById(classVo.getCurriculumId());

            LocalDate startDate = DateUtils.parseDate(entity.getStartDate()).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate endDate = DateUtils.parseDate(entity.getEndDate()).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();



            if(entity.getType().equals("1")){

                for (int i = 0; i <entity.getFrequency().intValue() ; i++) {

                    kjBo=new TbKjBo();
                    kjBo.setSortCurriculumId(entity.getId());
                    kjBo.setCreatedDate(new Date());
                    kjBo.setName("第"+(i+1)+"节课");
                    kjBo.setClassId(entity.getClassId());
                    kjBo.setStartHour(entity.getStartHour());
                    kjBo.setEndHour(entity.getEndHour());
                    kjBo.setCourseDuration(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,DateUtils.addDays(DateUtils.parseDate(entity.getStartDate()),entity.getFrequency().intValue())));

                    kjService.insertByBo(kjBo);
                }

            }else if(entity.getType().equals("2")){


                if(bo.getJsfs().equals("1")){

                    for (int i = 0; i <entity.getFrequency().intValue() ; i++) {
                        kjBo=new TbKjBo();
                        kjBo.setSortCurriculumId(entity.getId());
                        kjBo.setCreatedDate(new Date());
                        kjBo.setName("第"+(i+1)+"节课");
                        kjBo.setClassId(entity.getClassId());
                        kjBo.setStartHour(entity.getStartHour());
                        kjBo.setEndHour(entity.getEndHour());
                        kjBo.setCourseDuration(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,DateUtils.addDays(DateUtils.parseDate(entity.getStartDate()),(i))));
                        kjService.insertByBo(kjBo);
                    }

                }else if(bo.getJsfs().equals("2")){
                    long days = Duration.between(startDate.atStartOfDay(), endDate.atStartOfDay()).toDays();

                    for (int i = 0; i <=days ; i++) {
                        kjBo=new TbKjBo();
                        kjBo.setSortCurriculumId(entity.getId());
                        kjBo.setCreatedDate(new Date());
                        kjBo.setName("第"+(i+1)+"节课");
                        kjBo.setClassId(entity.getClassId());
                        kjBo.setStartHour(entity.getStartHour());
                        kjBo.setEndHour(entity.getEndHour());
                        kjBo.setCourseDuration(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,DateUtils.addDays(DateUtils.parseDate(entity.getStartDate()),(i))));
                        kjService.insertByBo(kjBo);
                    }

                }

            }else if(entity.getType().equals("3")){

                if(bo.getJsfs().equals("1")){

                    int cs=0;
                    int insert=0;

                    while (insert<entity.getFrequency().intValue()){
                        Date myDate=DateUtils.addDays(DateUtils.parseDate(entity.getStartDate()),(cs));
                        Integer dayOfWeek = DateUtil.dayOfWeekEnum(myDate).getValue();

                        if(entity.getWeekly().contains(dayOfWeek.toString())){
                            kjBo=new TbKjBo();
                            kjBo.setSortCurriculumId(entity.getId());
                            kjBo.setCreatedDate(new Date());
                            kjBo.setName("第"+(insert+1)+"节课");
                            kjBo.setClassId(entity.getClassId());
                            kjBo.setStartHour(entity.getStartHour());
                            kjBo.setEndHour(entity.getEndHour());
                            kjBo.setCourseDuration(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,myDate));
                            kjService.insertByBo(kjBo);

                            insert++;
                        }


                        cs++;
                    }

                }else if(bo.getJsfs().equals("2")){
                    long days = Duration.between(startDate.atStartOfDay(), endDate.atStartOfDay()).toDays();

                    for (int i = 0; i <=days ; i++) {

                        Date myDate=DateUtils.addDays(DateUtils.parseDate(entity.getStartDate()),(i));
                        Integer dayOfWeek = DateUtil.dayOfWeekEnum(myDate).getValue();
                        if(!entity.getWeekly().contains(dayOfWeek.toString())){
                            continue;
                        }

                        kjBo=new TbKjBo();
                        kjBo.setSortCurriculumId(entity.getId());
                        kjBo.setCreatedDate(new Date());
                        kjBo.setName("第"+(i+1)+"节课");
                        kjBo.setClassId(entity.getClassId());
                        kjBo.setStartHour(entity.getStartHour());
                        kjBo.setEndHour(entity.getEndHour());
                        kjBo.setCourseDuration(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,myDate));
                        kjService.insertByBo(kjBo);
                    }
                }


            }

        }
    }

    /**
     * 批量删除排课
     */
    @Transactional
    @Override
    public Boolean deleteWithValidByIds(List<Long> ids, Boolean isValid) {
        if(isValid){
            for (int i = 0; i <ids.size() ; i++) {
                long count=kjService.selectCount(new LambdaQueryWrapper<TbKj>()
                    .eq(TbKj::getSortCurriculumId,ids.get(i))
                );

                if(count>0){
                    throw new ServiceException("排课下还有课节，不能删除。");
                }

            }
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
